package cn.xy.base.server.web;

import cn.hutool.crypto.SecureUtil;
import cn.xy.commons.annotation.RepeatSubmit;
import cn.xy.commons.cache.CacheManager;
import cn.xy.commons.web.RequestUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 防止表单重复提交
 *
 *  @author xy
 */
@Slf4j
@Component
public class RepeatSubmitService {

    private static final String CACHE_KEY = "FormRepeatSubmit_";

    /**
     * 保存时间
     */
    private static final int CACHE_TIME = 1;

    @Autowired
    private CacheManager cacheManager;

    public boolean prevent(int userId, HttpServletRequest request, Object handler) {
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Method method = handlerMethod.getMethod();
            RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class);
            return annotation != null && this.isRepeatSubmit(userId, request);
        }
        return false;
    }

    private boolean isRepeatSubmit(int userId, HttpServletRequest request) {
        String key = CACHE_KEY + request.getRequestURI() + "_" + userId;
        String submitLog = cacheManager.get(key);
        String dataSha1 = this.getDataSha1(request);
        if (dataSha1.equals(submitLog)) {
            return true;
        }
        cacheManager.set(key, dataSha1, CACHE_TIME);
        return false;
    }

    private String getDataSha1(HttpServletRequest request) {
        // param数据
        Map<String, String[]> parameterMap = request.getParameterMap();
        List<String> paramList = new ArrayList<>();
        for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
            String[] params = entry.getValue();
            paramList.add(entry.getKey() + String.join("", params));
        }
        paramList = paramList.stream().sorted().collect(Collectors.toList());
        String paramStr = String.join("", paramList);
        // 结果
        String body = RequestUtil.getBody(request);
        return SecureUtil.sha1(paramStr + body);
    }

}
